﻿#include "stdafx.h"

#include "QtWidgetsClass.h"

#include "ErosionTask.h"

#include <ImageTaskFactory.h>

QtWidgetsClass::QtWidgetsClass(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	initUi();
	initConnections();


}

QtWidgetsClass::~QtWidgetsClass()
{}




/**
 * @brief 添加任务项到 QListWidget
 * @param task 任务对象的 unique_ptr，所有权将被转移
 */
void QtWidgetsClass::addTaskItem(std::unique_ptr<ImageTask> task) {
	// 创建 QListWidgetItem，显示任务名称
	QListWidgetItem* item = new QListWidgetItem(task->getName().c_str(), ui.taskListWidget);
	ui.taskListWidget->addItem(item);

	// 保存 item 和 task 的映射
	ImageTask* taskPtr = task.get();
	itemToTaskMap[item] = taskPtr;

	// 将任务所有权转移到 taskManager
	taskManager.addTask(std::move(task));
}


/**
 * @brief 双击任务项时显示配置界面
 * @param item 被双击的 QListWidgetItem
 */
void QtWidgetsClass::onTaskItemDoubleClicked(QListWidgetItem* item) {
	if (itemToTaskMap.find(item) != itemToTaskMap.end()) {
		ImageTask* task = itemToTaskMap[item];
		std::unique_ptr<QDialog> dialog = task->getConfigUI(); // 获取任务的配置界面
		if (dialog) {
			dialog->exec(); // 显示配置对话框
		}
	}
}

/**
 * @brief 点击执行按钮时触发
 */
void QtWidgetsClass::on_pushButton_execute_clicked()
{
	// 使用 QtConcurrent::run 在后台线程执行任务
	QFuture<void> future = QtConcurrent::run([this]() {
		taskManager.executeAll(); // 执行所有任务
		});

	// 创建 QFutureWatcher 监控任务完成
	QFutureWatcher<void>* watcher = new QFutureWatcher<void>(this);

	// 先连接信号，再设置 future，避免竞争条件
	connect(watcher, &QFutureWatcher<void>::finished, this, [this, watcher]() {
		const std::vector<cv::Mat>& results = taskManager.getIntermediateResults();
		if (!results.empty()) {
			displayImage(results.back()); // 在主线程更新 UI
		}
		watcher->deleteLater(); // 清理 watcher
		});

	// 设置 future
	watcher->setFuture(future);
}


void QtWidgetsClass::on_toolButton_decrease_clicked()
{
	// 获取当前选中的项
	QListWidgetItem* currentItem = ui.taskListWidget->currentItem();
	if (currentItem) {
		// 获取选中项的索引
		int row = ui.taskListWidget->row(currentItem);

		// 从 taskManager 中移除任务（假设 TaskManager 有 removeTask 方法）
		taskManager.removeTask(row);

		// 从 itemToTaskMap 中移除映射
		itemToTaskMap.erase(currentItem);

		// 从 taskListWidget 中移除项并释放内存
		delete ui.taskListWidget->takeItem(row);
	}

	
		
}

/**
 * @brief 显示图像
 * @param image 要显示的图像
 */
void QtWidgetsClass::displayImage(const cv::Mat& image) {
	// 转换为 RGB 格式（Qt 使用 RGB，而 OpenCV 默认是 BGR）
	cv::Mat rgbImage;
	cv::cvtColor(image, rgbImage, cv::COLOR_BGR2RGB);

	if (rgbImage.cols > static_cast<size_t>(std::numeric_limits<int>::max()) ||
		rgbImage.rows > static_cast<size_t>(std::numeric_limits<int>::max()) ||
		rgbImage.step > static_cast<size_t>(std::numeric_limits<int>::max())) {
		throw std::runtime_error("Image dimensions or step exceed int range");
	}
	// 创建 QImage
	QImage qImage(rgbImage.data,
		static_cast<int>(rgbImage.cols),
		static_cast<int>(rgbImage.rows),
		static_cast<int>(rgbImage.step),
		QImage::Format_RGB888);

	// 创建 QPixmap 并缩放以适应 resultLabel
	QPixmap pixmap = QPixmap::fromImage(qImage);
	QPixmap scaledPixmap = pixmap.scaled(
		resultLabel->size(),         // 使用 resultLabel 的当前大小
		Qt::KeepAspectRatio,        // 保持图片宽高比
		Qt::SmoothTransformation    // 平滑缩放，保证显示质量
	);

	// 设置缩放后的图片到 resultLabel
	resultLabel->setPixmap(scaledPixmap);
	resultLabel->setScaledContents(false); // 禁用自动缩放
}

/**
 * @brief 初始化 UI
 */
void QtWidgetsClass::initUi()
{
	//最大化
	setWindowState(Qt::WindowMaximized);
	// 设置任务列表右键菜单
	ui.taskListWidget->setContextMenuPolicy(Qt::CustomContextMenu);

	// 设置结果显示区域 (frame_2)
	QVBoxLayout* resultLayout = new QVBoxLayout(ui.frame_2);
	resultLabel = new QLabel(ui.frame_2);
	resultLabel->setAlignment(Qt::AlignCenter);
	resultLayout->addWidget(resultLabel);

	initMenu();

}


void QtWidgetsClass::initMenu()
{
	taskMenu = new QMenu(this);

	

	// 动态生成分组菜单
	for (const auto& [groupName, taskTypes] : ImageTaskFactory::taskGroups) {
		QMenu* groupMenu = taskMenu->addMenu(QString::fromStdString(groupName)); // 创建子菜单
		for (const auto& type : taskTypes) {
			try {
				std::string taskName = ImageTaskFactory::taskTypeNames.at(type).toStdString();
				QAction* action = groupMenu->addAction(QString::fromStdString(taskName));
				action->setData(static_cast<int>(type)); // 存储 TaskType
				connect(action, &QAction::triggered, this, [this, action]() {
					onTaskTypeSelected(action); // 显式调用槽，传递 action
					});
			}
			catch (const std::out_of_range& e) {
				qDebug() << "Task type not found in taskTypeNames:" << static_cast<int>(type);
				// 提供默认名称或跳过
				QAction* action = groupMenu->addAction("未知任务");
				action->setData(static_cast<int>(type));
				connect(action, &QAction::triggered, this, [this, action]() {
					onTaskTypeSelected(action); // 显式调用槽，传递 action
					});
			}
		}
	}

	ui.toolButton_append->setMenu(taskMenu);
	ui.toolButton_append->setPopupMode(QToolButton::InstantPopup); // 点击时立即弹出菜单
	ui.toolButton_append->setStyleSheet("QToolButton::menu-indicator { image: none; }");

}

/**
 * @brief 初始化信号槽连接
 */
void QtWidgetsClass::initConnections()
{
	connect(ui.taskListWidget, &QListWidget::customContextMenuRequested, this, &QtWidgetsClass::onContextItemRequested);
	connect(ui.taskListWidget, &QListWidget::itemDoubleClicked, this, &QtWidgetsClass::onTaskItemDoubleClicked);
	connect(ui.ImgAction, &QAction::triggered, this, [this]() {
		// 打开文件对话框，选择图片文件
		QString filePath = QFileDialog::getOpenFileName(this,
			tr("选择图片"),
			"C:\\Users\\li\\Pictures\\2025.3.7XCY\\2025.3.7",
			tr("图片文件 (*.png *.jpg *.jpeg *.bmp)"));

		if (!filePath.isEmpty()) {
			// 使用 OpenCV 的 cv::Mat 读取图片
			cv::Mat matImage = cv::imread(filePath.toLocal8Bit().toStdString());
			if (matImage.empty()) {
				QMessageBox::warning(this, tr("错误"), tr("无法加载图片！"));
				return;
			}

			taskManager.setOriginalImage(matImage);
			displayImage(matImage); // 显示图片

		}
		});
}

/**
 * @brief 选择任务类型时触发
 * @param action 选择的 QAction
 */
void QtWidgetsClass::onTaskTypeSelected(QAction* action) {
	// 从 QAction 的 data 中获取 TaskType
	TaskType type = static_cast<TaskType>(action->data().toInt());

	// 使用工厂方法创建新任务
	std::unique_ptr<ImageTask> newTask = ImageTaskFactory::createTask(type);
	if (!newTask) return; // 如果任务创建失败，直接返回

	// 获取当前选中的项
	QListWidgetItem* currentItem = ui.taskListWidget->currentItem();
	int insertRow = -1;

	if (currentItem) {
		// 如果有选中项，插入到它的下一行
		insertRow = ui.taskListWidget->row(currentItem) + 1;
	}
	else {
		// 如果没有选中项，插入到列表末尾
		insertRow = ui.taskListWidget->count();
	}

	// 创建新的 QListWidgetItem 并插入到指定位置
	QListWidgetItem* newItem = new QListWidgetItem(newTask->getName().c_str());
	ui.taskListWidget->insertItem(insertRow, newItem);

	// 更新 itemToTaskMap 和 taskManager
	itemToTaskMap[newItem] = newTask.get(); // 假设 itemToTaskMap 是任务映射
	taskManager.insertTask(insertRow, std::move(newTask)); // 插入任务到 taskManager
}


void QtWidgetsClass::onContextItemRequested(const QPoint& pos) {
	QListWidgetItem* item = ui.taskListWidget->itemAt(pos); // 获取点击的项
	if (item) {
		int step = ui.taskListWidget->row(item); // 获取对应的步骤索引
		cv::Mat result = taskManager.executeToStep(step); // 执行到该步骤
		if (!result.empty()) {
			displayImage(result); // 显示结果图像（需自行实现）
		}
		else {
			QMessageBox::warning(this, "警告", "无法获取图像！");
		}
	}
}

